<script setup>
import { onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { useAudioStore } from '@/stores/audioStore'
import { getSongLyricAPi } from '@/apis/song'
const useAudio = useAudioStore()

const songLyric = ref({})
const timerArr = ref([])
const lyricArr = ref([])
const songTlyric = ref({})
const tlyricTimeArr = ref([])
const tlyricArr = ref([])
const lyricIndex = ref(-1)
const lyricUl = ref(null)

// 正在播放的歌曲发生变化，重新获取歌曲
watch(() => useAudio.songResult, () => {
  handleGetLyric()
})

// 组件挂载时获取歌词
onMounted(async () => {
  handleGetLyric()
})

// 封装获取歌词的函数
const handleGetLyric = async () => {
  lyricArr.value = []
  tlyricArr.value = []
  useAudio.audioRef.removeEventListener('timeupdate', rollingLyric)
  if (!useAudio.songResult.id) return
  const { data } = await getSongLyricAPi(useAudio.songResult.id)
  if (data.sgc) return
  songLyric.value = data.lrc.lyric
  songTlyric.value = data.tlyric.lyric
  handleLyric()
}

// 组件卸载前，清除歌词滚动的侦听器函数
onBeforeUnmount(() => {
  useAudio.audioRef.removeEventListener('timeupdate', rollingLyric)
})

// 处理歌词
const handleLyric = () => {
  timerArr.value = []
  lyricArr.value = []
  tlyricArr.value = []
  tlyricTimeArr.value = []
  // 提取歌曲内容，将时间与歌词分别放入各自的数组内
  const reg = /\[(\d{2}:\d{2}.\d{2,3})\](.+)/g
  let tmp
  while ((tmp = reg.exec(songLyric.value)) !== null) {
    timerArr.value.push(tmp[1])
    lyricArr.value.push(tmp[2])
  }

  // 判断是否需要翻译
  if (isTranslate.value) {
    translateLyric()
  }

  lyricIndex.value = (timerArr.value.findIndex(item => item > formatTime(useAudio.currentTime))) - 1

  // 判断是否获取到歌词
  if (lyricArr.value.length !== 0) {
    // 绑定事件（监听播放器的时间变化）
    useAudio.audioRef.addEventListener('timeupdate', rollingLyric)
  }
}

// 歌词滚动播放
const rollingLyric = () => {
  if (lyricIndex.value !== -1) {
    [...lyricUl.value.children].forEach(item => { item.className = '' })
    lyricUl.value.children[lyricIndex.value].className = 'active'
    const lyricHeight = lyricUl.value.querySelectorAll('li')[lyricIndex.value].offsetTop
    lyricUl.value.style.top = -lyricHeight + 400 + 'px'
  }
  // 格式化拿到的时间
  const timeStr = formatTime(useAudio.currentTime)
  // 在时间数组中找到对应的索引
  lyricIndex.value = timerArr.value.findIndex(item => item.slice(0, item.length - 3) === timeStr.slice(0, item.length - 3))
}

// 封装的格式化时长函数 mm:sss
const formatTime = (time) => {
  const minutes = parseInt(time / 60)
  const seconds = (time % 60).toFixed(3)
  return (minutes < 10 ? '0' + minutes : minutes) + ':' + (seconds < 10 ? '0' + seconds : seconds)
}

// 是否翻译翻译中文
const isTranslate = ref(true)
watch(isTranslate, () => {
  if (isTranslate.value) {
    translateLyric()
  } else {
    handleLyric()
  }
})
// 封装的歌词翻译函数
const translateLyric = () => {
  const reg2 = /\[(\d{2}:\d{2}.\d{2,3})\](.+\s)/g
  let tmp1
  while ((tmp1 = reg2.exec(songTlyric.value)) !== null) {
    tlyricTimeArr.value.push(tmp1[1])
    tlyricArr.value.push(tmp1[2])
  }
  const index = timerArr.value.indexOf(tlyricTimeArr.value[0])
  tlyricArr.value.forEach((item, itemIndex) => {
    lyricArr.value[index + itemIndex] = lyricArr.value[index + itemIndex] + '<br />' + item
  })
  lyricIndex.value = (timerArr.value.findIndex(item => item > formatTime(useAudio.currentTime))) - 1
}

</script>

<template>
  <div>
    <div class="song-lyric-box">
      <ul ref="lyricUl">
        <li v-if="!useAudio.songResult.id">去播放喜欢的歌曲吧</li>
        <li v-if="useAudio.songResult.id && lyricArr.length === 0">暂时无歌词</li>
        <li v-for="(item, index) in lyricArr" :key="index">
          <div v-html="item"></div>
        </li>
      </ul>
      <div v-show="songTlyric.length > 0">
        <div class="translate-icon" @click="isTranslate = false" v-show="isTranslate">
          <i class="iconfont icon-fanyi"></i>
        </div>
        <div class="translate-icon" @click="isTranslate = true" v-show="!isTranslate">
          <i class="iconfont icon-fanyi fanyi-inactive"></i>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped lang='scss'>
.song-lyric-box {
  position: relative;
  height: 90vh;
  width: 600px;
  overflow: hidden;

  &::after {
    content: '';
    position: absolute;
    z-index: 200;
    width: 700px;
    height: 50px;
    top: -30px;
    box-shadow: 0px 20px 30px #e4ddff;
  }

  ul {
    transition: 0.6s;
    position: absolute;
    top: 400px;
    left: 0;
    bottom: 0;
    right: 0;
  }

  :deep(li) {
    text-align: center;
    color: #aaa;
    margin-bottom: 18px;
    line-height: 30px;
    font-size: 16px;
  }

  :deep(.active) {
    color: $sucColor;
  }

  .translate-icon {
    position: absolute;
    cursor: pointer;
    bottom: 20px;
    right: 0;

    .icon-fanyi {
      font-size: 24px;
    }

    .fanyi-inactive {
      color: #aaa;
    }
  }
}
</style>
